React์ `experimental_useEvent` ํ ์ ๋ํ ์ฌ์ธต ๋ถ์์ผ๋ก, ์ด ํ ์ด ์ด๋ป๊ฒ stale closure ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๊ณ , React ์ ํ๋ฆฌ์ผ์ด์ ์ ์ฑ๋ฅ๊ณผ ์์ธก ๊ฐ๋ฅ์ฑ ํฅ์์ ์ํด ์์ ์ ์ธ ์ด๋ฒคํธ ํธ๋ค๋ฌ ์ฐธ์กฐ๋ฅผ ์ ๊ณตํ๋์ง ์ค๋ช ํฉ๋๋ค.
React์ `experimental_useEvent`: ์์ ์ ์ธ ์ด๋ฒคํธ ํธ๋ค๋ฌ ์ฐธ์กฐ ๋ง์คํฐํ๊ธฐ
React ๊ฐ๋ฐ์๋ ์ด๋ฒคํธ ํธ๋ค๋ฌ๋ฅผ ๋ค๋ฃฐ ๋ ์ข
์ข
๋๋ ค์ด "stale closure" ๋ฌธ์ ์ ์ง๋ฉดํฉ๋๋ค. ์ด ๋ฌธ์ ๋ ์ปดํฌ๋ํธ๊ฐ ๋ฆฌ๋ ๋๋ง๋ ๋ ์ด๋ฒคํธ ํธ๋ค๋ฌ๊ฐ ์ฃผ๋ณ ์ค์ฝํ์์ ์ค๋๋ ๊ฐ์ ์บก์ฒํ ๋ ๋ฐ์ํฉ๋๋ค. React์ experimental_useEvent ํ
์ ์ด ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๊ณ ์์ ์ ์ธ ์ด๋ฒคํธ ํธ๋ค๋ฌ ์ฐธ์กฐ๋ฅผ ์ ๊ณตํ๊ธฐ ์ํด ์ค๊ณ๋์์ผ๋ฉฐ, ์ฑ๋ฅ๊ณผ ์์ธก ๊ฐ๋ฅ์ฑ์ ํฅ์์ํค๋ ๊ฐ๋ ฅํ (ํ์ฌ๋ ์คํ์ ์ธ) ๋๊ตฌ์
๋๋ค. ์ด ๊ธ์์๋ experimental_useEvent์ ๋ชฉ์ , ์ฌ์ฉ๋ฒ, ์ด์ ๋ฐ ์ ์ฌ์ ์ธ ๋จ์ ์ ์ค๋ช
ํ๋ฉฐ ๊ทธ ๋ณต์ก์ฑ์ ๊น์ด ํ๊ณ ๋ญ๋๋ค.
Stale Closure ๋ฌธ์ ์ดํดํ๊ธฐ
experimental_useEvent๋ฅผ ์ดํด๋ณด๊ธฐ ์ ์, ์ด ํ
์ด ํด๊ฒฐํ๋ ๋ฌธ์ ์ธ stale closure์ ๋ํ ์ดํด๋ฅผ ํ์คํ ํด๋ด
์๋ค. ๋ค์์ ๊ฐ๋จํ ์๋๋ฆฌ์ค๋ฅผ ๊ณ ๋ คํด ๋ณด์ธ์:
import React, { useState, useEffect } from 'react';
function MyComponent() {
const [count, setCount] = useState(0);
useEffect(() => {
const timer = setInterval(() => {
console.log("Count inside interval: ", count);
}, 1000);
return () => clearInterval(timer);
}, []); // Empty dependency array - runs only once on mount
return (
<div>
<p>Count: {count}</p>
<button onClick={() => setCount(count + 1)}>Increment</button>
</div>
);
}
export default MyComponent;
์ด ์์ ์์, ๋น ์์กด์ฑ ๋ฐฐ์ด์ ๊ฐ์ง useEffect ํ
์ ์ปดํฌ๋ํธ๊ฐ ๋ง์ดํธ๋ ๋ ํ ๋ฒ๋ง ์คํ๋ฉ๋๋ค. setInterval ํจ์๋ count์ ์ด๊ธฐ๊ฐ(0)์ ์บก์ฒํฉ๋๋ค. "Increment" ๋ฒํผ์ ํด๋ฆญํ์ฌ count ์ํ๋ฅผ ์
๋ฐ์ดํธํ๋๋ผ๋, setInterval ์ฝ๋ฐฑ์ ๊ณ์ํด์ "Count inside interval: 0"์ ๊ธฐ๋กํ ๊ฒ์
๋๋ค. ์๋ํ๋ฉด ํด๋ก์ ๋ด์ ์บก์ฒ๋ count ๊ฐ์ด ๋ณ๊ฒฝ๋์ง ์๊ธฐ ๋๋ฌธ์
๋๋ค. ์ด๊ฒ์ด ๋ฐ๋ก stale closure์ ์ ํ์ ์ธ ์ฌ๋ก์
๋๋ค. ์ธํฐ๋ฒ์ ๋ค์ ์์ฑ๋์ง ์์ผ๋ฉฐ ์๋ก์ด 'count' ๊ฐ์ ๊ฐ์ ธ์ค์ง ๋ชปํฉ๋๋ค.
์ด ๋ฌธ์ ๋ ์ธํฐ๋ฒ์๋ง ๊ตญํ๋์ง ์์ต๋๋ค. ํจ์๊ฐ ์๊ฐ์ด ์ง๋จ์ ๋ฐ๋ผ ๋ณํ ์ ์๋ ์ฃผ๋ณ ์ค์ฝํ์ ๊ฐ์ ์บก์ฒํ๋ ๋ชจ๋ ์ํฉ์์ ๋ํ๋ ์ ์์ต๋๋ค. ์ผ๋ฐ์ ์ธ ์๋๋ฆฌ์ค๋ ๋ค์๊ณผ ๊ฐ์ต๋๋ค:
- ์ด๋ฒคํธ ํธ๋ค๋ฌ(
onClick,onChange๋ฑ) - ์๋ํํฐ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ์ ๋ฌ๋๋ ์ฝ๋ฐฑ
- ๋น๋๊ธฐ ์์
(
setTimeout,fetch)
`experimental_useEvent` ์๊ฐ
React์ ์คํ์ ๊ธฐ๋ฅ์ ์ผ๋ถ๋ก ๋์
๋ experimental_useEvent๋ ์์ ์ ์ธ ์ด๋ฒคํธ ํธ๋ค๋ฌ ์ฐธ์กฐ๋ฅผ ์ ๊ณตํจ์ผ๋ก์จ stale closure ๋ฌธ์ ๋ฅผ ์ฐํํ๋ ๋ฐฉ๋ฒ์ ์ ๊ณตํฉ๋๋ค. ๊ฐ๋
์ ์ผ๋ก ๋ค์๊ณผ ๊ฐ์ด ์๋ํฉ๋๋ค:
- ๋ฆฌ๋ ๋๋ง ํ์๋ ํญ์ ์ต์ ๋ฒ์ ์ ์ด๋ฒคํธ ํธ๋ค๋ฌ ๋ก์ง์ ์ฐธ์กฐํ๋ ํจ์๋ฅผ ๋ฐํํฉ๋๋ค.
- ๋ถํ์ํ ์ด๋ฒคํธ ํธ๋ค๋ฌ ์ฌ์์ฑ์ ๋ฐฉ์งํ์ฌ ๋ฆฌ๋ ๋๋ง์ ์ต์ ํํ๊ณ ์ฑ๋ฅ์ ํฅ์์ํต๋๋ค.
- ์ปดํฌ๋ํธ ๋ด์์ ๊ด์ฌ์ฌ์ ๋ถ๋ฆฌ๋ฅผ ๋ ๋ช ํํ๊ฒ ์ ์งํ๋ ๋ฐ ๋์์ ์ค๋๋ค.
์ค์ ์ฌํญ: ์ด๋ฆ์์ ์ ์ ์๋ฏ์ด, experimental_useEvent๋ ์์ง ์คํ ๋จ๊ณ์ ์์ต๋๋ค. ์ด๋ ํฅํ React ๋ฆด๋ฆฌ์ค์์ API๊ฐ ๋ณ๊ฒฝ๋ ์ ์์์ ์๋ฏธํ๋ฉฐ, ์์ง ํ๋ก๋์
ํ๊ฒฝ์์์ ์ฌ์ฉ์ ๊ณต์์ ์ผ๋ก ๊ถ์ฅ๋์ง ์์ต๋๋ค. ํ์ง๋ง ๊ทธ ๋ชฉ์ ๊ณผ ์ ์ฌ์ ์ด์ ์ ์ดํดํ๋ ๊ฒ์ ๊ฐ์น๊ฐ ์์ต๋๋ค.
`experimental_useEvent` ์ฌ์ฉ ๋ฐฉ๋ฒ
experimental_useEvent๋ฅผ ํจ๊ณผ์ ์ผ๋ก ์ฌ์ฉํ๋ ๋ฐฉ๋ฒ์ ๋ํ ์ค๋ช
์
๋๋ค:
- ์ค์น:
๋จผ์ , ์คํ์ ๊ธฐ๋ฅ์ ์ง์ํ๋ React ๋ฒ์ ์ ์ฌ์ฉํ๊ณ ์๋์ง ํ์ธํ์ธ์.
react์react-dom์ ์คํ์ ํจํค์ง๋ฅผ ์ค์นํด์ผ ํ ์๋ ์์ต๋๋ค (์คํ์ ๋ฆด๋ฆฌ์ค์ ๋ํ ์ต์ ์ง์นจ ๋ฐ ์ฃผ์ ์ฌํญ์ ๊ณต์ React ๋ฌธ์๋ฅผ ํ์ธํ์ธ์):npm install react@experimental react-dom@experimental - ํ
๊ฐ์ ธ์ค๊ธฐ:
reactํจํค์ง์์experimental_useEventํ ์ ๊ฐ์ ธ์ต๋๋ค:import { experimental_useEvent } from 'react'; - ์ด๋ฒคํธ ํธ๋ค๋ฌ ์ ์:
ํ์ํ ์ํ๋ props๋ฅผ ์ฐธ์กฐํ์ฌ ํ์์ฒ๋ผ ์ด๋ฒคํธ ํธ๋ค๋ฌ ํจ์๋ฅผ ์ ์ํฉ๋๋ค.
- `experimental_useEvent` ์ฌ์ฉํ๊ธฐ:
์ด๋ฒคํธ ํธ๋ค๋ฌ ํจ์๋ฅผ ์ ๋ฌํ์ฌ
experimental_useEvent๋ฅผ ํธ์ถํฉ๋๋ค. ๊ทธ๋ฌ๋ฉด JSX์์ ์ฌ์ฉํ ์ ์๋ ์์ ์ ์ธ ์ด๋ฒคํธ ํธ๋ค๋ฌ ํจ์๋ฅผ ๋ฐํํฉ๋๋ค.
๋ค์์ experimental_useEvent๋ฅผ ์ฌ์ฉํ์ฌ ์ด์ ์ธํฐ๋ฒ ์์ ์ stale closure ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๋ ์์์
๋๋ค:
import React, { useState, useEffect, experimental_useEvent } from 'react';
function MyComponent() {
const [count, setCount] = useState(0);
const intervalCallback = () => {
console.log("Count inside interval: ", count);
};
const stableIntervalCallback = experimental_useEvent(intervalCallback);
useEffect(() => {
const timer = setInterval(() => {
stableIntervalCallback();
}, 1000);
return () => clearInterval(timer);
}, []); // Empty dependency array - runs only once on mount
return (
<div>
<p>Count: {count}</p>
<button onClick={() => setCount(count + 1)}>Increment</button>
</div>
);
}
export default MyComponent;
์ด์ "Increment" ๋ฒํผ์ ํด๋ฆญํ๋ฉด, setInterval ์ฝ๋ฐฑ์ด ์
๋ฐ์ดํธ๋ count ๊ฐ์ ์ ํํ๊ฒ ๊ธฐ๋กํ ๊ฒ์
๋๋ค. ์ด๋ stableIntervalCallback์ด ํญ์ ์ต์ ๋ฒ์ ์ intervalCallback ํจ์๋ฅผ ์ฐธ์กฐํ๊ธฐ ๋๋ฌธ์
๋๋ค.
`experimental_useEvent` ์ฌ์ฉ์ ์ด์
experimental_useEvent ์ฌ์ฉ์ ์ฃผ์ ์ด์ ์ ๋ค์๊ณผ ๊ฐ์ต๋๋ค:
- Stale Closure ์ ๊ฑฐ: ์ด๋ฒคํธ ํธ๋ค๋ฌ๊ฐ ํญ์ ์ฃผ๋ณ ์ค์ฝํ์ ์ต์ ๊ฐ์ ์บก์ฒํ๋๋ก ๋ณด์ฅํ์ฌ ์๊ธฐ์น ์์ ๋์๊ณผ ๋ฒ๊ทธ๋ฅผ ๋ฐฉ์งํฉ๋๋ค.
- ์ฑ๋ฅ ํฅ์: ์์ ์ ์ธ ์ฐธ์กฐ๋ฅผ ์ ๊ณตํจ์ผ๋ก์จ ์ด๋ฒคํธ ํธ๋ค๋ฌ์ ์์กดํ๋ ์์ ์ปดํฌ๋ํธ์ ๋ถํ์ํ ๋ฆฌ๋ ๋๋ง์ ๋ฐฉ์งํฉ๋๋ค. ์ด๋
React.memo๋useMemo๋ฅผ ์ฌ์ฉํ๋ ์ต์ ํ๋ ์ปดํฌ๋ํธ์ ํนํ ์ ์ฉํฉ๋๋ค. - ์ฝ๋ ๋จ์ํ: ๊ฐ๋ณ ๊ฐ์ ์ ์ฅํ๊ธฐ ์ํด
useRefํ ์ ์ฌ์ฉํ๊ฑฐ๋useEffect์ ์์กด์ฑ์ ์๋์ผ๋ก ์ ๋ฐ์ดํธํ๋ ๋ฑ์ ํด๊ฒฐ ๋ฐฉ๋ฒ์ ์ ๊ฑฐํ์ฌ ์ฝ๋๋ฅผ ๋จ์ํํ ์ ์์ต๋๋ค. - ์์ธก ๊ฐ๋ฅ์ฑ ์ฆ๊ฐ: ์ปดํฌ๋ํธ์ ๋์์ ๋ ์์ธก ๊ฐ๋ฅํ๊ณ ์ถ๋ก ํ๊ธฐ ์ฝ๊ฒ ๋ง๋ค์ด, ์ ์ง๋ณด์๊ฐ ๋ ์ฉ์ดํ ์ฝ๋๋ฅผ ์์ฑํ ์ ์๊ฒ ํฉ๋๋ค.
`experimental_useEvent`๋ ์ธ์ ์ฌ์ฉํด์ผ ํ ๊น?
๋ค์๊ณผ ๊ฐ์ ๊ฒฝ์ฐ experimental_useEvent ์ฌ์ฉ์ ๊ณ ๋ คํด ๋ณด์ธ์:
- ์ด๋ฒคํธ ํธ๋ค๋ฌ๋ ์ฝ๋ฐฑ์์ stale closure๋ฅผ ๊ฒช๊ณ ์์ ๋.
- ๋ถํ์ํ ๋ฆฌ๋ ๋๋ง์ ๋ฐฉ์งํ์ฌ ์ด๋ฒคํธ ํธ๋ค๋ฌ์ ์์กดํ๋ ์ปดํฌ๋ํธ์ ์ฑ๋ฅ์ ์ต์ ํํ๊ณ ์ถ์ ๋.
- ์ด๋ฒคํธ ํธ๋ค๋ฌ ๋ด์์ ๋ณต์กํ ์ํ ์ ๋ฐ์ดํธ๋ ๋น๋๊ธฐ ์์ ์ ๋ค๋ฃฐ ๋.
- ๋ ๋๋ง ๊ฐ์ ๋ณ๊ฒฝ๋์ง ์์์ผ ํ์ง๋ง ์ต์ ์ํ์ ์ ๊ทผํด์ผ ํ๋ ํจ์์ ๋ํ ์์ ์ ์ธ ์ฐธ์กฐ๊ฐ ํ์ํ ๋.
ํ์ง๋ง experimental_useEvent๊ฐ ์์ง ์คํ์ ์ด๋ผ๋ ์ ์ ๊ธฐ์ตํ๋ ๊ฒ์ด ์ค์ํฉ๋๋ค. ํ๋ก๋์
์ฝ๋์์ ์ฌ์ฉํ๊ธฐ ์ ์ ์ ์ฌ์ ์ธ ์ํ๊ณผ ์ฅ๋จ์ ์ ๊ณ ๋ คํ์ธ์.
์ ์ฌ์ ์ธ ๋จ์ ๋ฐ ๊ณ ๋ ค์ฌํญ
experimental_useEvent๋ ์๋นํ ์ด์ ์ ์ ๊ณตํ์ง๋ง, ์ ์ฌ์ ์ธ ๋จ์ ์ ์ธ์งํ๋ ๊ฒ์ด ์ค์ํฉ๋๋ค:
- ์คํ์ ์ํ: API๋ ํฅํ React ๋ฆด๋ฆฌ์ค์์ ๋ณ๊ฒฝ๋ ์ ์์ต๋๋ค. ์ด๋ฅผ ์ฌ์ฉํ๋ฉด ๋์ค์ ์ฝ๋๋ฅผ ๋ฆฌํฉํ ๋งํด์ผ ํ ์๋ ์์ต๋๋ค.
- ๋ณต์ก์ฑ ์ฆ๊ฐ: ์ด๋ค ๊ฒฝ์ฐ์๋ ์ฝ๋๋ฅผ ๋จ์ํํ ์ ์์ง๋ง, ์ ์คํ๊ฒ ์ฌ์ฉํ์ง ์์ผ๋ฉด ๋ณต์ก์ฑ์ ๋ํ ์๋ ์์ต๋๋ค.
- ์ ํ๋ ๋ธ๋ผ์ฐ์ ์ง์: ์๋ก์ด ์๋ฐ์คํฌ๋ฆฝํธ ๊ธฐ๋ฅ์ด๋ React ๋ด๋ถ์ ์์กดํ๋ฏ๋ก, ๊ตฌํ ๋ธ๋ผ์ฐ์ ์์๋ ํธํ์ฑ ๋ฌธ์ ๊ฐ ์์ ์ ์์ต๋๋ค (React์ ํด๋ฆฌํ์ด ์ผ๋ฐ์ ์ผ๋ก ์ด ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ์ง๋ง).
- ๊ณผ์ฉ ๊ฐ๋ฅ์ฑ: ๋ชจ๋ ์ด๋ฒคํธ ํธ๋ค๋ฌ๋ฅผ
experimental_useEvent๋ก ๊ฐ์ ํ์๋ ์์ต๋๋ค. ๊ณผ๋ํ๊ฒ ์ฌ์ฉํ๋ฉด ๋ถํ์ํ ๋ณต์ก์ฑ์ ์ด๋ํ ์ ์์ต๋๋ค.
`experimental_useEvent`์ ๋์
์คํ์ ์ธ ๊ธฐ๋ฅ ์ฌ์ฉ์ ์ฃผ์ ํ๋ค๋ฉด, stale closure ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๋ ๋ฐ ๋์์ด ๋๋ ๋ช ๊ฐ์ง ๋์์ด ์์ต๋๋ค:
- `useRef` ์ฌ์ฉํ๊ธฐ:
useRefํ ์ ์ฌ์ฉํ์ฌ ๋ฆฌ๋ ๋๋ง ๊ฐ์ ์ ์ง๋๋ ๊ฐ๋ณ ๊ฐ์ ์ ์ฅํ ์ ์์ต๋๋ค. ์ด๋ฅผ ํตํด ์ด๋ฒคํธ ํธ๋ค๋ฌ ๋ด์์ ์ํ๋ props์ ์ต์ ๊ฐ์ ์ ๊ทผํ ์ ์์ต๋๋ค. ํ์ง๋ง ๊ด๋ จ ์ํ๋ prop์ด ๋ณ๊ฒฝ๋ ๋๋ง๋ค ref์.current์์ฑ์ ์๋์ผ๋ก ์ ๋ฐ์ดํธํด์ผ ํฉ๋๋ค. ์ด๋ ๋ณต์ก์ฑ์ ์ผ๊ธฐํ ์ ์์ต๋๋ค.import React, { useState, useEffect, useRef } from 'react'; function MyComponent() { const [count, setCount] = useState(0); const countRef = useRef(count); useEffect(() => { countRef.current = count; }, [count]); useEffect(() => { const timer = setInterval(() => { console.log("Count inside interval: ", countRef.current); }, 1000); return () => clearInterval(timer); }, []); return ( <div> <p>Count: {count}</p> <button onClick={() => setCount(count + 1)}>Increment</button> </div> ); } export default MyComponent; - ์ธ๋ผ์ธ ํจ์:
์ด๋ค ๊ฒฝ์ฐ์๋ JSX ๋ด์ ์ด๋ฒคํธ ํธ๋ค๋ฌ๋ฅผ ์ธ๋ผ์ธ์ผ๋ก ์ ์ํ์ฌ stale closure๋ฅผ ํผํ ์ ์์ต๋๋ค. ์ด๋ ๊ฒ ํ๋ฉด ์ด๋ฒคํธ ํธ๋ค๋ฌ๊ฐ ํญ์ ์ต์ ๊ฐ์ ์ ๊ทผํ ์ ์์ต๋๋ค. ํ์ง๋ง ์ด๋ฒคํธ ํธ๋ค๋ฌ๊ฐ ๊ณ์ฐ ๋น์ฉ์ด ๋ง์ด ๋๋ ๊ฒฝ์ฐ, ๋ ๋๋ง๋ง๋ค ๋ค์ ์์ฑ๋๋ฏ๋ก ์ฑ๋ฅ ๋ฌธ์ ๋ฅผ ์ผ์ผํฌ ์ ์์ต๋๋ค.
import React, { useState } from 'react'; function MyComponent() { const [count, setCount] = useState(0); return ( <div> <p>Count: {count}</p> <button onClick={() => { console.log("Current count: ", count); setCount(count + 1); }}>Increment</button> </div> ); } export default MyComponent; - ํจ์ํ ์
๋ฐ์ดํธ:
์ด์ ์ํ์ ์์กดํ๋ ์ํ ์ ๋ฐ์ดํธ์ ๊ฒฝ์ฐ,
setState์ ํจ์ํ ์ ๋ฐ์ดํธ ํํ๋ฅผ ์ฌ์ฉํ ์ ์์ต๋๋ค. ์ด๋ ๊ฒ ํ๋ฉด stale closure์ ์์กดํ์ง ์๊ณ ๊ฐ์ฅ ์ต๊ทผ์ ์ํ ๊ฐ์ผ๋ก ์์ ํ ์ ์์ต๋๋ค.import React, { useState } from 'react'; function MyComponent() { const [count, setCount] = useState(0); return ( <div> <p>Count: {count}</p> <button onClick={() => setCount(prevCount => prevCount + 1)}>Increment</button> </div> ); } export default MyComponent;
์ค์ ์ฌ๋ก ๋ฐ ์ฌ์ฉ ์์
experimental_useEvent(๋๋ ๊ทธ ๋์)๊ฐ ํนํ ์ ์ฉํ ์ ์๋ ๋ช ๊ฐ์ง ์ค์ ์ฌ๋ก๋ฅผ ์ดํด๋ณด๊ฒ ์ต๋๋ค:
- ์๋ ์ ์/์๋ ์์ฑ ์ปดํฌ๋ํธ: ์๋ ์ ์ ๋๋ ์๋ ์์ฑ ์ปดํฌ๋ํธ๋ฅผ ๊ตฌํํ ๋, ์ข
์ข
์ฌ์ฉ์ ์
๋ ฅ์ ๊ธฐ๋ฐํ์ฌ ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ ธ์์ผ ํฉ๋๋ค. ์
๋ ฅ์
onChange์ด๋ฒคํธ ํธ๋ค๋ฌ์ ์ ๋ฌ๋ ์ฝ๋ฐฑ ํจ์๊ฐ ์ ๋ ฅ ํ๋์ ์ค๋๋ ๊ฐ์ ์บก์ฒํ ์ ์์ต๋๋ค.experimental_useEvent๋ฅผ ์ฌ์ฉํ๋ฉด ์ฝ๋ฐฑ์ด ํญ์ ์ต์ ์ ๋ ฅ ๊ฐ์ ์ ๊ทผํ์ฌ ๋ถ์ ํํ ๊ฒ์ ๊ฒฐ๊ณผ๋ฅผ ๋ฐฉ์งํ ์ ์์ต๋๋ค. - ์ด๋ฒคํธ ํธ๋ค๋ฌ ๋๋ฐ์ด์ฑ/์ฐ๋กํ๋ง: ์ด๋ฒคํธ ํธ๋ค๋ฌ๋ฅผ ๋๋ฐ์ด์ฑํ๊ฑฐ๋ ์ฐ๋กํ๋งํ ๋(์: API ํธ์ถ ๋น๋ ์ ํ), ํ์ด๋จธ ID๋ฅผ ๋ณ์์ ์ ์ฅํด์ผ ํฉ๋๋ค. ํ์ด๋จธ ID๊ฐ stale closure์ ์ํด ์บก์ฒ๋๋ฉด ๋๋ฐ์ด์ฑ ๋๋ ์ฐ๋กํ๋ง ๋ก์ง์ด ์ ๋๋ก ์๋ํ์ง ์์ ์ ์์ต๋๋ค.
experimental_useEvent๋ ํ์ด๋จธ ID๊ฐ ํญ์ ์ต์ ์ํ๋ฅผ ์ ์งํ๋๋ก ๋์์ค๋๋ค. - ๋ณต์กํ ํผ ์ฒ๋ฆฌ: ์ฌ๋ฌ ์
๋ ฅ ํ๋์ ์ ํจ์ฑ ๊ฒ์ฌ ๋ก์ง์ด ์๋ ๋ณต์กํ ํผ์์๋ ํน์ ์
๋ ฅ ํ๋์
onChange์ด๋ฒคํธ ํธ๋ค๋ฌ ๋ด์์ ๋ค๋ฅธ ์ ๋ ฅ ํ๋์ ๊ฐ์ ์ ๊ทผํด์ผ ํ ์ ์์ต๋๋ค. ์ด๋ฌํ ๊ฐ๋ค์ด stale closure์ ์ํด ์บก์ฒ๋๋ฉด ์ ํจ์ฑ ๊ฒ์ฌ ๋ก์ง์ด ์๋ชป๋ ๊ฒฐ๊ณผ๋ฅผ ์์ฑํ ์ ์์ต๋๋ค. - ์๋ํํฐ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์์ ํตํฉ: ์ฝ๋ฐฑ์ ์์กดํ๋ ์๋ํํฐ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ํตํฉํ ๋, ์ฝ๋ฐฑ์ด ์ ๋๋ก ๊ด๋ฆฌ๋์ง ์์ผ๋ฉด stale closure๋ฅผ ๋ง๋ ์ ์์ต๋๋ค.
experimental_useEvent๋ ์ฝ๋ฐฑ์ด ํญ์ ์ต์ ๊ฐ์ ์ ๊ทผํ๋๋ก ๋ณด์ฅํ๋ ๋ฐ ๋์์ด ๋ ์ ์์ต๋๋ค.
์ด๋ฒคํธ ํธ๋ค๋ง์ ๋ํ ๊ตญ์ ์ ๊ณ ๋ ค์ฌํญ
๊ธ๋ก๋ฒ ์ฌ์ฉ์๋ฅผ ๋์์ผ๋ก ํ๋ React ์ ํ๋ฆฌ์ผ์ด์ ์ ๊ฐ๋ฐํ ๋, ์ด๋ฒคํธ ํธ๋ค๋ง์ ๋ํด ๋ค์๊ณผ ๊ฐ์ ๊ตญ์ ์ ๊ณ ๋ ค์ฌํญ์ ์ผ๋์ ๋์ธ์:
- ํค๋ณด๋ ๋ ์ด์์: ์ธ์ด๋ง๋ค ํค๋ณด๋ ๋ ์ด์์์ด ๋ค๋ฆ ๋๋ค. ์ด๋ฒคํธ ํธ๋ค๋ฌ๊ฐ ๋ค์ํ ํค๋ณด๋ ๋ ์ด์์์ ์ ๋ ฅ์ ์ฌ๋ฐ๋ฅด๊ฒ ์ฒ๋ฆฌํ๋์ง ํ์ธํ์ธ์. ์๋ฅผ ๋ค์ด, ํน์ ๋ฌธ์์ ๋ฌธ์ ์ฝ๋๋ ๋ค๋ฅผ ์ ์์ต๋๋ค.
- ์
๋ ฅ๊ธฐ(IME): IME๋ ์ค๊ตญ์ด๋ ์ผ๋ณธ์ด ๋ฌธ์์ฒ๋ผ ํค๋ณด๋์์ ์ง์ ์ฌ์ฉํ ์ ์๋ ๋ฌธ์๋ฅผ ์
๋ ฅํ๋ ๋ฐ ์ฌ์ฉ๋ฉ๋๋ค. ์ด๋ฒคํธ ํธ๋ค๋ฌ๊ฐ IME์ ์
๋ ฅ์ ์ฌ๋ฐ๋ฅด๊ฒ ์ฒ๋ฆฌํ๋์ง ํ์ธํ์ธ์.
compositionstart,compositionupdate,compositionend์ด๋ฒคํธ์ ์ฃผ์๋ฅผ ๊ธฐ์ธ์ด์ธ์. - ์ค๋ฅธ์ชฝ์์ ์ผ์ชฝ(RTL)์ผ๋ก ์ฐ๋ ์ธ์ด: ์ ํ๋ฆฌ์ผ์ด์ ์ด ์๋์ด๋ ํ๋ธ๋ฆฌ์ด์ ๊ฐ์ RTL ์ธ์ด๋ฅผ ์ง์ํ๋ ๊ฒฝ์ฐ, ๋ฏธ๋ฌ๋ง๋ ๋ ์ด์์์ ๊ณ ๋ คํ์ฌ ์ด๋ฒคํธ ํธ๋ค๋ฌ๋ฅผ ์กฐ์ ํด์ผ ํ ์ ์์ต๋๋ค. ์ด๋ฒคํธ์ ๊ธฐ๋ฐํ์ฌ ์์๋ฅผ ๋ฐฐ์นํ ๋ ๋ฌผ๋ฆฌ์ ์์ฑ ๋์ CSS์ ๋ ผ๋ฆฌ์ ์์ฑ์ ๊ณ ๋ คํ์ธ์.
- ์ ๊ทผ์ฑ(a11y): ์ด๋ฒคํธ ํธ๋ค๋ฌ๊ฐ ์ฅ์ ๊ฐ ์๋ ์ฌ์ฉ์๋ ์ ๊ทผํ ์ ์๋๋ก ํ์ธ์. ์๋งจํฑ HTML ์์์ ARIA ์์ฑ์ ์ฌ์ฉํ์ฌ ์ด๋ฒคํธ ํธ๋ค๋ฌ์ ๋ชฉ์ ๊ณผ ๋์์ ๋ํ ์ ๋ณด๋ฅผ ๋ณด์กฐ ๊ธฐ์ ์ ์ ๊ณตํ์ธ์. ํค๋ณด๋ ๋ค๋น๊ฒ์ด์ ์ ํจ๊ณผ์ ์ผ๋ก ์ฌ์ฉํ์ธ์.
- ์๊ฐ๋: ์ ํ๋ฆฌ์ผ์ด์
์ด ์๊ฐ์ ๋ฏผ๊ฐํ ์ด๋ฒคํธ๋ฅผ ํฌํจํ๋ ๊ฒฝ์ฐ, ์๊ฐ๋์ ์ผ๊ด ์ ์ฝ ์๊ฐ์ ๋ฅผ ์ผ๋์ ๋์ธ์. ์๊ฐ๋ ๋ณํ์ ์ฒ๋ฆฌํ๊ธฐ ์ํด ์ ์ ํ ๋ผ์ด๋ธ๋ฌ๋ฆฌ(์:
moment-timezone๋๋date-fns-tz)๋ฅผ ์ฌ์ฉํ์ธ์. - ์ซ์ ๋ฐ ๋ ์ง ์์: ์ซ์์ ๋ ์ง์ ํ์์ ๋ฌธํ๊ถ๋ง๋ค ํฌ๊ฒ ๋ค๋ฅผ ์ ์์ต๋๋ค. ์ฌ์ฉ์์ ๋ก์บ์ ๋ฐ๋ผ ์ซ์์ ๋ ์ง์ ์์์ ์ง์ ํ๊ธฐ ์ํด ์ ์ ํ ๋ผ์ด๋ธ๋ฌ๋ฆฌ(์:
Intl.NumberFormat๋ฐIntl.DateTimeFormat)๋ฅผ ์ฌ์ฉํ์ธ์.
๊ฒฐ๋ก
experimental_useEvent๋ React์์ stale closure ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๊ณ ์ ํ๋ฆฌ์ผ์ด์
์ ์ฑ๋ฅ๊ณผ ์์ธก ๊ฐ๋ฅ์ฑ์ ํฅ์์ํค๋ ์ ๋งํ ๋๊ตฌ์
๋๋ค. ์์ง ์คํ์ ์ด์ง๋ง, ์ด๋ฒคํธ ํธ๋ค๋ฌ ์ฐธ์กฐ๋ฅผ ํจ๊ณผ์ ์ผ๋ก ๊ด๋ฆฌํ๊ธฐ ์ํ ๊ฐ๋ ฅํ ํด๊ฒฐ์ฑ
์ ์ ๊ณตํฉ๋๋ค. ๋ค๋ฅธ ์ ๊ธฐ์ ๊ณผ ๋ง์ฐฌ๊ฐ์ง๋ก, ํ๋ก๋์
์์ ์ฌ์ฉํ๊ธฐ ์ ์ ๊ทธ ์ด์ , ๋จ์ ๋ฐ ๋์์ ์ ์คํ๊ฒ ๊ณ ๋ คํ๋ ๊ฒ์ด ์ค์ํฉ๋๋ค. experimental_useEvent์ ๋ฏธ๋ฌํ ์ฐจ์ด์ ๊ทธ๊ฒ์ด ํด๊ฒฐํ๋ ๊ทผ๋ณธ์ ์ธ ๋ฌธ์ ๋ฅผ ์ดํดํจ์ผ๋ก์จ, ๊ธ๋ก๋ฒ ์ฌ์ฉ์๋ฅผ ์ํ ๋ ๊ฒฌ๊ณ ํ๊ณ , ์ฑ๋ฅ์ด ๋ฐ์ด๋๋ฉฐ, ์ ์ง๋ณด์๊ฐ ์ฉ์ดํ React ์ฝ๋๋ฅผ ์์ฑํ ์ ์์ต๋๋ค.
์คํ์ ๊ธฐ๋ฅ์ ๋ํ ์ต์ ์ ๋ฐ์ดํธ ๋ฐ ๊ถ์ฅ ์ฌํญ์ ๊ณต์ React ๋ฌธ์๋ฅผ ์ฐธ์กฐํ๋ ๊ฒ์ ์์ง ๋ง์ธ์. ์ฆ๊ฑฐ์ด ์ฝ๋ฉ ๋์ธ์!